home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 1
/
Cream of the Crop 1.iso
/
PROGRAM
/
FDF101.ARJ
/
FDFCOMM.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-04-29
|
12KB
|
546 lines
/*
* fdfcomm.c
*
* common functions for find duplicates program
*
* Roy Bixler
* March 23, 1991
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 1, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <ctype.h>
#include <dir.h>
#include <dos.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <sys\types.h> /* must be included before stat.h */
#include <sys\stat.h>
#include "cmp.h"
#include "fdfcomm.h"
#include "elib.h"
FILE_LIST *F_list = NULL, *I_del_menu[N_INTERACTIVE];
char Match_criteria = 0, Sort_criteria = 0, Sort_order = ASCENDING;
char i_flag = 0; /* interactive delete mode */
char l_flag = 0; /* long listing? */
char v_flag = 0; /* verbose? */
static char Sorted;
/*
* print_fdate
*
* given a dta structure, print out the date in it
*/
void print_fdate(struct ffblk *dta)
{
printf("%02d/%02d/%02d",
(dta->ff_fdate >> 9) + 80,
(dta->ff_fdate >> 5) & 0xf,
(dta->ff_fdate) & 0x1f);
}
/*
* print_ftime
*
* given a dta structure, print out the time in it
*/
void print_ftime(struct ffblk *dta)
{
printf("%02d:%02d:%02d",
(dta->ff_ftime >> 11),
(dta->ff_ftime >> 5) & 0x3f,
(dta->ff_ftime & 0x1f));
}
/*
* print_fdatetime
*
* print the given dta's date, a space and the dta's time
*/
void print_fdatetime(struct ffblk *dta)
{
print_fdate(dta);
printf(" ");
print_ftime(dta);
}
/*
* print_fpath
*
* given a path and a dta, print the path with the dta's name tacked on the
* end
*/
void print_fpath(char *path, char *f_name)
{
static char *dir_sep = PATH_SEPARATOR;
int path_len;
if (path != NULL) {
path_len = strlen(path);
printf("%s%s%s", path,
((path_len > 0) && (path[path_len-1] == dir_sep[0]))
? ""
: PATH_SEPARATOR,
f_name);
}
}
/*
* long_listing
*
* print out the complete information on the given file
*/
void long_listing(char *path, struct ffblk *dta)
{
if (path != NULL) {
printf("%c ", (dta->ff_attrib == 0x10) ? 'd' : '-');
print_fdatetime(dta);
printf(" %8ld ", dta->ff_fsize);
print_fpath(path, dta->ff_name);
printf("\n");
}
}
/*
* print_match_header
*
* prints the first match of files
*/
void print_match_header(FILE_LIST *start)
{
if (l_flag)
return; /* no header */
else if (Match_criteria & NAMES_MATCH)
printf("file %s found in directories:\n", start->dta.ff_name);
else if (Match_criteria & CONTENTS_MATCH)
printf("files with matching contents (size = %ld) found:\n",
start->dta.ff_fsize);
else if (Match_criteria & SIZES_MATCH)
printf("files of length %ld found:\n", start->dta.ff_fsize);
else if (Match_criteria & TIMES_MATCH) {
printf("files with timestamp ");
print_fdatetime(&start->dta);
printf(" found:\n");
}
}
/*
* print_next_match
*
* prints out any matches after the first one
*/
void print_next_match(FILE_LIST *next, int menu_num)
{
if (menu_num >= 0)
printf("%d)%s", menu_num, (l_flag) ? " " : "");
if (l_flag)
long_listing(next->path, &next->dta);
else if (Match_criteria & NAMES_MATCH)
printf("\t%s\n", next->path);
else {
printf("\t"); print_fpath(next->path, next->dta.ff_name);
printf("\n");
}
next->printed = 1;
}
/*
* print_id_menu
*
* given a starting point in the file list, print out an interactive delete
* menu.
*/
void print_id_menu(FILE_LIST **menu, int num_items)
{
int i;
print_match_header(menu[0]);
for (i = 0; i < num_items; i++)
print_next_match(menu[i], i+1);
}
/*
* cmpflist
*
* returns non-zero if the FILE_LIST parameter is less/greater than the given
* dta/path combination according to the sort criteria. If sort
* order is ASCENDING, non-zero returned if FILE_LIST less than dta/path
* combo, vice-versa for DESCENDING order.
*/
int cmpflist(FILE_LIST *fd, char *path, struct ffblk *dta)
{
long cmptime_tmp;
int tmp;
switch (Sort_criteria) {
case NAME_SORT:
return (Sort_order == ASCENDING)
? (((tmp = strcmp(fd->dta.ff_name, dta->ff_name)) < 0) ||
((tmp == 0) && (strcmp(fd->path, path) <= 0)))
: (((tmp = strcmp(fd->dta.ff_name, dta->ff_name)) > 0) ||
((tmp == 0) && (strcmp(fd->path, path) >= 0)));
case SIZE_SORT:
return (Sort_order == ASCENDING)
? ((fd->dta.ff_fsize < dta->ff_fsize) ||
((fd->dta.ff_fsize == dta->ff_fsize) &&
(strcmp(fd->dta.ff_name, dta->ff_name) < 0)) ||
((fd->dta.ff_fsize == dta->ff_fsize) &&
(strcmp(fd->path, path) <= 0)))
: ((fd->dta.ff_fsize > dta->ff_fsize) ||
((fd->dta.ff_fsize == dta->ff_fsize) &&
(strcmp(fd->dta.ff_name, dta->ff_name) > 0)) ||
((fd->dta.ff_fsize == dta->ff_fsize) &&
(strcmp(fd->path, path) >= 0)));
case TIME_SORT:
return (Sort_order == ASCENDING)
? (((cmptime_tmp = cmptime(&fd->dta, dta)) < 0) ||
((cmptime_tmp == 0) &&
((tmp = strcmp(fd->dta.ff_name,
dta->ff_name)) < 0)) ||
((tmp == 0) && (strcmp(fd->path, path) <= 0)))
: (((cmptime_tmp = cmptime(&fd->dta, dta)) > 0) ||
((cmptime_tmp == 0) &&
((tmp = strcmp(fd->dta.ff_name,
dta->ff_name)) > 0)) ||
((tmp == 0) && (strcmp(fd->path, path) >= 0)));
default:
return 0; /* unknown sort criteria */
}
}
/*
* cmpflist_eq
*
* returns non-zero if the two FILE_LIST parameters are equal according to the
* sort criteria.
*/
int cmpflist_eq(FILE_LIST *fd1, FILE_LIST *fd2)
{
if (fd1 == NULL)
return (fd2 == NULL);
else if (fd2 == NULL)
return 0;
switch (Sort_criteria) {
case NAME_SORT:
return !strcmp(fd1->dta.ff_name, fd2->dta.ff_name);
case SIZE_SORT:
return (fd1->dta.ff_fsize == fd2->dta.ff_fsize);
case TIME_SORT:
return !cmptime(&fd1->dta, &fd2->dta);
default:
return 0; /* unknown sort criteria */
}
}
/*
* files_match
*
* return non-zero if the given two files 'match' according to names and the
* criteria set by the flags (contents, date/time, size or almost any
* combination of these).
*/
int files_match(FILE_LIST *file1, FILE_LIST *file2)
{
return (((!(Match_criteria & NAMES_MATCH)) ||
(!strcmp(file1->dta.ff_name, file2->dta.ff_name))) &&
((!(Match_criteria & SIZES_MATCH)) ||
(file1->dta.ff_fsize == file2->dta.ff_fsize)) &&
((!(Match_criteria & TIMES_MATCH)) ||
(!cmptime(&file1->dta, &file2->dta))) &&
((!(Match_criteria & CONTENTS_MATCH)) ||
(compare_path_name_files(file1->path, file1->dta.ff_name,
file2->path, file2->dta.ff_name))));
}
/*
* gen_list
*
* given a path, generate a list of all files in the path and its
* subdirectories.
*/
void gen_list(char *path)
{
struct ffblk dta;
char *path_list, *save_path;
if (path == NULL)
return;
path_list = append_dir_to_path(path, ADD_TO_PATH);
if ((findfirst(path_list, &dta, FA_DIREC) >= 0) &&
((save_path = malloc((size_t) (strlen(path)+1))) != NULL)) {
strcpy(save_path, path);
do {
if (dta.ff_attrib & FA_DIREC)
gen_list_of_dir(path, dta.ff_name);
else
add_file_to_list(save_path, &dta);
} while (!findnext(&dta));
}
free(path_list);
}
/*
* add_file_to_list
*
* given a path and a file on the path, add it to the list according to the
* sort criteria.
*/
void add_file_to_list(char *path, struct ffblk *dta)
{
FILE_LIST *prev = NULL, *new, *cur = F_list;
if (Sorted)
while ((cur != NULL) && (cmpflist(cur, path, dta))) {
prev = cur;
cur = cur->next;
}
if ((new = malloc((size_t) sizeof(FILE_LIST))) == NULL) {
printf("add_file_to_list: memory allocation failure\n");
exit(-1);
}
else {
memcpy(&new->dta, dta, sizeof(struct ffblk));
new->path = path;
new->added = 0;
new->printed = 0;
new->next = cur;
if (prev == NULL)
F_list = new;
else
prev->next = new;
}
}
/*
* gen_list_of_dir
*
* given a path and a sub-directory, call 'gen_list()' to generate a list
* of the sub-directory on the path.
*/
void gen_list_of_dir(char *path, char *subdir)
{
char *new_path;
if (!is_special(subdir)) {
gen_list(new_path = append_dir_to_path(path, subdir));
if (v_flag > 1) {
printf("Searching ");
print_fpath(path, subdir);
printf("\n");
}
free(new_path);
}
}
/*
* list_files
*
* given a path, generate a linked list of files on the path or (recursively)
* its subdirectories. If 'sorted' is non-zero, make sure the list is
* sorted.
*/
void list_files(char *prog_name, char *path, char sorted)
{
struct stat statbuf;
static char target_dir[MAX_STR];
if (just_disk(path)){
get_cur_path(path, target_dir);
path = target_dir;
}
if ((access(path, 0)) || ((!stat(path, &statbuf)) &&
(!(statbuf.st_mode & S_IFDIR)))) {
printf("%s: directory %s does not exist\n", prog_name, path);
print_help();
exit(-1);
}
else {
Sorted = sorted;
gen_list(path);
if (v_flag > 1)
printf("\n");
}
}
void get_cur_path(char *new, char *target_dir)
{
char cur_dir[MAX_STR];
getcwd(cur_dir, MAX_STR);
change_disk(new, cur_dir);
getcwd(target_dir, MAX_STR);
setdisk(*cur_dir - 'A');
chdir(cur_dir);
}
void change_disk(char *dir, char *cur_dir)
{
int maxdrives;
if (isupper(*dir))
tolower(*dir);
maxdrives = setdisk(*dir - 'a');
if (maxdrives < (*dir - 'a') + 1){
setdisk(*cur_dir - 'A');
printf("drive '%c' is not accessable\n", *dir);
print_help();
exit(-1);
}
}
/*
* just_disk()
*
* Input:
* dir - the directory to be checked
* Output:
* returns :
* 1 - if 'dir' is a current directory (ie 'X:')
* 0 - otherwise
*/
int just_disk(char *dir)
{
if ((strlen(dir) == 2) && (*(dir + 1) == ':'))
return(1);
else
return(0);
}
/*
* print_flist
*
* given a pointer to the first entry of a file list, dump the list to standard
* output
*/
void print_flist(FILE_LIST *flist)
{
for (;flist != NULL; flist = flist->next)
printf("path = %s\tname = %s\n", flist->path, flist->dta.ff_name);
}
/*
* compare_path_name_files
*
* given a pair of files specified by path and name, return non-zero if their
* contents match, zero if contents don't match.
*/
int compare_path_name_files(char *path1, char *name1, char *path2, char *name2)
{
int ret_val;
char *file1;
char *file2;
file1 = append_dir_to_path(path1, name1);
file2 = append_dir_to_path(path2, name2);
if ((file1 == NULL) || (file2 == NULL)) {
printf("compare_path_name_files: memory allocation failed!\n");
exit(-1);
}
ret_val = compare_files(file1, file2);
free(file1);
free(file2);
return ret_val;
}
/*
* delete_path_name_file
*
* given a file specified by path and name, return zero if the file was
* successfully deleted, non-zero if not. 'force' parameter, if non-zero, will
* try to change the mode of a file from read-only to delete it.
*/
int delete_path_name_file(char *path, char *f_name, char force)
{
char *file = append_dir_to_path(path, f_name);
int ret_val;
if (file == NULL) {
printf("delete_path_name_file: memory allocation failed\n");
exit(-1);
}
ret_val = delete_file(file, force);
free(file);
return ret_val;
}